package kk.learn.scala.work._5

import java.util.Date

import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.scheduling.annotation.{EnableScheduling, Scheduled}
import org.springframework.web.bind.annotation.{GetMapping, RestController}
import org.springframework.web.servlet.tags.Param

import scala.collection.mutable


/**
 * <p>
 *  使用Spring， 运行起一个Scala实例
 * </p>
 *
 * @author KK
 * @since 2021-02-22
 */
object Master extends App{
    SpringApplication.run(classOf[Master])
}

@SpringBootApplication
@RestController
@EnableScheduling
class Master {
  val workerInfos: mutable.Map[String, WorkerInfo] = scala.collection.mutable.Map[String, WorkerInfo]()

  val invalidTime:Long = 10000

  // worker注册端点
  @GetMapping(value = Array("register"))
  def register(workerId:String ): String = {
    val workerInfo = new WorkerInfo(workerId)
    workerInfo.latestHeartBeatTime = new Date()
    workerInfos.put(workerId, workerInfo)
    println(s"worker注册:$workerInfo")
    println(s"当前所有worker的信息:$workerInfos")
     "ok"
  }

  // worker心跳端点
  @GetMapping(value = Array("heartBeat"))
  def heartBeat(workerId:String ): String = {
    val workerInfo = workerInfos.getOrElse(workerId, null)
    workerInfo.latestHeartBeatTime = new Date()
    println(s"worker心跳， 更新后的workerInfo信息:$workerInfo")
    println(s"当前所有worker的信息:$workerInfos")
    "ok"
  }

  // 删除latestHeartBeatTime超时的worker， 不断调度， 延迟为一秒
  @Scheduled(fixedDelay =  1000L)
  def clearInvalidedWorker():Unit = {
//    println("检查是否有worker无效.......")
    // 记录无效的id
    val invalidWorkerIds:mutable.MutableList[String] = new mutable.MutableList[String]
    for ( (key, workerInfo)<- workerInfos ) {
      if (System.currentTimeMillis() - workerInfo.latestHeartBeatTime.getTime > invalidTime){
        invalidWorkerIds += key
      }
    }

    // 删除无效的worker
    if (invalidWorkerIds.nonEmpty){
      for (workerId <- invalidWorkerIds) {
        println(s"删除无效worker: $workerId")
        workerInfos.remove(workerId)
      }
      println(s"当前有效的worker: $workerInfos")
    }


  }

}


class WorkerInfo(val workerId: String) {
  var latestHeartBeatTime: Date = _
  override def toString = s"WorkerInfo(latestHeartBeatTime=$latestHeartBeatTime, workerId=$workerId)"
}
